home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / security / log_tcp_6.0alpha.shar / rfc931.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-02  |  4.1 KB  |  161 lines

  1.  /*
  2.   * rfc931_user() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
  3.   * protocols. It consults an RFC 931 etc. compatible daemon on the client
  4.   * host to look up the remote user name. The information should not be used
  5.   * for authentication purposes.
  6.   * 
  7.   * Diagnostics are reported through syslog(3).
  8.   * 
  9.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  10.   * 
  11.   * Inspired by the authutil package (comp.sources.unix volume 22) by Dan
  12.   * Bernstein (brnstnd@kramden.acf.nyu.edu).
  13.   */
  14.  
  15. #ifndef lint
  16. static char sccsid[] = "@(#) rfc931.c 1.5 93/07/02 16:33:36";
  17. #endif
  18.  
  19. #include <stdio.h>
  20. #include <syslog.h>
  21. #include <sys/types.h>
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #include <setjmp.h>
  25. #include <signal.h>
  26. #ifdef TLI
  27. #include <sys/timod.h>
  28. #include <stropts.h>
  29. #include <tiuser.h>
  30. #endif
  31.  
  32. #include "log_tcp.h"
  33.  
  34. #define    RFC931_PORT    113        /* Semi-well-known port */
  35.  
  36. #ifndef RFC931_TIMEOUT
  37. #define    RFC931_TIMEOUT    30        /* wait for at most 30 seconds */
  38. #endif
  39.  
  40. extern char *strchr();
  41. extern char *inet_ntoa();
  42.  
  43. static jmp_buf timebuf;
  44.  
  45. /* timeout - handle timeouts */
  46.  
  47. static void timeout(sig)
  48. int     sig;
  49. {
  50.     longjmp(timebuf, sig);
  51. }
  52.  
  53. /* rfc931_name - return remote user name */
  54.  
  55. char   *rfc931_name(there)
  56. struct sockaddr_in *there;        /* remote link information */
  57. {
  58.     struct sockaddr_in here;        /* local link information */
  59.     struct sockaddr_in sin;        /* for talking to RFC931 daemon */
  60.     int     length;
  61.     int     s;
  62.     unsigned remote;
  63.     unsigned local;
  64.     static char user[256];        /* XXX */
  65.     char    buffer[512];        /* YYY */
  66.     FILE   *fp;
  67.     char   *cp;
  68.     char   *result = FROM_UNKNOWN;
  69.  
  70.     /* Find out local address and port number of stdin. */
  71.  
  72.     length = sizeof(here);
  73. #ifdef TLI
  74.     if (isastream(0) && ioctl(0, I_FIND, "timod") > 0) {
  75.     struct netbuf nb;
  76.  
  77.     nb.buf = (char *) &here;
  78.     nb.maxlen = length;
  79.     if (ioctl(0, TI_GETMYNAME, &nb) < 0) {
  80.         syslog(LOG_ERR, "TI_GETMYNAME: %m");
  81.         return (result);
  82.     }
  83.     } else
  84. #endif
  85.     if (getsockname(0, (struct sockaddr *) & here, &length) == -1) {
  86.     syslog(LOG_ERR, "getsockname: %m");
  87.     return (result);
  88.     }
  89.  
  90.     /*
  91.      * The socket that will be used for user name lookups should be bound to
  92.      * the same local IP address as stdin. This will automagically happen on
  93.      * hosts that have only one IP network address. When the local host has
  94.      * more than one IP network address, we must do an explicit bind() call.
  95.      */
  96.  
  97.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  98.     return (result);
  99.  
  100.     sin = here;
  101.     sin.sin_port = 0;
  102.     if (bind(s, (struct sockaddr *) & sin, sizeof sin) < 0) {
  103.     syslog(LOG_ERR, "bind: %s: %m", inet_ntoa(here.sin_addr));
  104.     return (result);
  105.     }
  106.     /* Set up timer so we won't get stuck. */
  107.  
  108.     signal(SIGALRM, timeout);
  109.     if (setjmp(timebuf)) {
  110.     close(s);                /* not: fclose(fp) */
  111.     return (result);
  112.     }
  113.     alarm(RFC931_TIMEOUT);
  114.  
  115.     /* Connect to the RFC931 daemon. */
  116.  
  117.     sin = *there;
  118.     sin.sin_port = htons(RFC931_PORT);
  119.     if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) == -1
  120.     || (fp = fdopen(s, "w+")) == 0) {
  121.     close(s);
  122.     alarm(0);
  123.     return (result);
  124.     }
  125.  
  126.     /*
  127.      * Use unbuffered I/O or we may read back our own query. setbuf() must be
  128.      * called before doing any I/O on the stream. Thanks for the reminder,
  129.      * Paul Kranenburg <pk@cs.few.eur.nl>!
  130.      */
  131.  
  132.     setbuf(fp, (char *) 0);
  133.  
  134.     /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
  135.  
  136.     fprintf(fp, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port));
  137.     fflush(fp);
  138.  
  139.     /*
  140.      * Read response from server. Use fgets()/sscanf() instead of fscanf()
  141.      * because there is no buffer for pushback. Thanks, Chris Turbeville
  142.      * <turbo@cse.uta.edu>.
  143.      */
  144.  
  145.     if (fgets(buffer, sizeof(buffer), fp) != 0
  146.     && ferror(fp) == 0 && feof(fp) == 0
  147.     && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  148.           &remote, &local, user) == 3
  149.     && ntohs(there->sin_port) == remote
  150.     && ntohs(here.sin_port) == local) {
  151.     /* Strip trailing carriage return. */
  152.  
  153.     if (cp = strchr(user, '\r'))
  154.         *cp = 0;
  155.     result = user;
  156.     }
  157.     alarm(0);
  158.     fclose(fp);
  159.     return (result);
  160. }
  161.